1 /* Copyright 2011-2013 The MathWorks, Inc. */
2 #include <stdio.h> /* sprintf */
3 #include <stdarg.h> /* variable argument lists */
4 #include "xil_interface_common.h"
5 #include "xil_data_stream.h"
6 #include "xil_common.h"
7 #include "target_io.h"
8 #include "rtwtypes.h"
9
10 /* test for ISO C99 or greater, which supports vsnprintf
11 *
12 * WARNING: if the compiler is ANSI C90 then we use vsprintf instead.
13 * Therefore, it is possible to overrun the buffer so the
14 * caller must take care not to exceed the buffer size!
15 */
16 #if __STDC_VERSION__ >= 199901L
17 #define VSNPRINTF_AVAILABLE
18 #endif
19
20 #ifndef TARGET_IO_BUFFER_SIZE
21 /* default buffer size is large enough for most use cases */
22 #define TARGET_IO_BUFFER_SIZE 64
23 #endif
24
25 #ifndef TARGET_IO_MAX_FILE_ID
26 /* -1 avoids warning about the comparison that is done
27 * in targetFopen
28 *
29 * note that MAX_uint16_T will be limited to uint16 max
30 * even when portable word sizes maps uint16 to a larger
31 * type such as uint32 on the SHARC */
32 #define TARGET_IO_MAX_FILE_ID (MAX_uint16_T - 1)
33 #endif
34
35 typedef enum {TARGET_IO_SUCCESS=0,
36 TARGET_IO_BUFFER_TRUNC } TARGET_IO_ERROR_ID;
37
38 static char targetStdioBuffer[TARGET_IO_BUFFER_SIZE];
39 #ifdef HOST_WORD_ADDRESSABLE_TESTING
40 static MemUnit_T hostWordStdioBuffer[TARGET_IO_BUFFER_SIZE];
41 #endif
42
43 /* fid is the file id on target and is limited to TARGET_IO_MAX_FILE_ID */
44 static uint16_T fid = 0;
45
46 /* call xilWriteData and check for errors */
47 static void targetWriteDataWithErrorCheck(const MemUnit_T *, uint32_T);
48 #ifdef HOST_WORD_ADDRESSABLE_TESTING
49 static void targetWriteDataWithCharToMemUnitWidening(const char *, MemUnit_T *, uint16_T);
50 #endif /* HOST_WORD_ADDRESSABLE_TESTING */
51
52 void targetWriteDataWithErrorCheck(const MemUnit_T * data, uint32_T size) {
53 if (xilWriteData(data, size) != XIL_DATA_STREAM_SUCCESS) {
54 for (;;) {
55 /* fatal comms error */
56 }
57 }
58 }
59
60 #ifdef HOST_WORD_ADDRESSABLE_TESTING
61 static void targetWriteDataWithCharToMemUnitWidening(const char *pCharBuff, MemUnit_T *pMemUnitBuff, uint16_T buffSize) {
62 uint16_T i;
63 for(i=0;i<buffSize;i++) {
64 pMemUnitBuff[i] = (MemUnit_T) pCharBuff[i];
65 }
66 targetWriteDataWithErrorCheck(pMemUnitBuff, buffSize * sizeof(MemUnit_T));
67 }
68 #endif
69
70 /* Forward a printf back to the host machine
71 *
72 * Printf size must not exceed the TARGET_IO_BUFFER_SIZE
73 * otherwise overflow will occur.
74 */
75 void targetPrintf(const char * fmt, ...) {
76 va_list argptr;
77 uint16_T printSize;
78 int vsPrintSize;
79 MemUnit_T responseId = XIL_RESPONSE_PRINTF;
80 MemUnit_T errorId = TARGET_IO_SUCCESS;
81
82 va_start(argptr, fmt);
83 #ifdef VSNPRINTF_AVAILABLE
84 /* size arg includes '\0', return value does not */
85 vsPrintSize = vsnprintf(&targetStdioBuffer[0], TARGET_IO_BUFFER_SIZE, fmt, argptr);
86 #else
87 vsPrintSize = vsprintf(&targetStdioBuffer[0], fmt, argptr);
88 #endif
89 if ((vsPrintSize < 0) || (vsPrintSize >= TARGET_IO_BUFFER_SIZE)) {
90 /* set error id if error or buffer overruns */
91 errorId = TARGET_IO_BUFFER_TRUNC;
92 /* do not send any data */
93 printSize = 0;
94 } else {
95 /* add one for the terminating null character */
96 printSize = (uint16_T) vsPrintSize + 1;
97 }
98 va_end(argptr);
99
100 /* send response id */
101 targetWriteDataWithErrorCheck(&responseId, sizeof(responseId));
102 /* send error id */
103 targetWriteDataWithErrorCheck(&errorId, sizeof(errorId));
104 /* send printSize */
105 targetWriteDataWithErrorCheck((MemUnit_T *) &printSize, sizeof(printSize));
106 /* send data */
107 if (printSize > 0) {
108 #ifdef HOST_WORD_ADDRESSABLE_TESTING
109 targetWriteDataWithCharToMemUnitWidening(&targetStdioBuffer[0], &hostWordStdioBuffer[0], printSize);
110 #else
111 targetWriteDataWithErrorCheck((MemUnit_T *)&targetStdioBuffer[0], printSize);
112 #endif
113 }
114 return;
115 }
116
117
118 /* Forward a fopen back to the host.
119 *
120 * fid is used on target to act as a valid
121 * "file descriptor".
122 */
123 unsigned short targetFopen(const char * fileName) {
124 uint16_T fileNameSize;
125 MemUnit_T responseId = XIL_RESPONSE_FOPEN;
126
127 /* size of file name string */
128 fileNameSize = (uint16_T) strlen(fileName);
129
130 /* add one for the terminating null character */
131 fileNameSize++;
132
133 /* check bounds and reset to 0 if necessary which will trigger an error
134 * on the host */
135 if(fid > TARGET_IO_MAX_FILE_ID) {
136 fid = 0;
137 }
138 /* send response id */
139 targetWriteDataWithErrorCheck(&responseId, sizeof(responseId));
140 /* send file id */
141 targetWriteDataWithErrorCheck((MemUnit_T *)&fid, sizeof(fid));
142 /* send size of file name string */
143 targetWriteDataWithErrorCheck((MemUnit_T *)&fileNameSize, sizeof(fileNameSize));
144 #ifdef HOST_WORD_ADDRESSABLE_TESTING
145 /* in case the total size is bigger than the hostWordStdioBuffer, send in
146 * multiple chunks */
147 {
148 while (fileNameSize > 0) {
149 uint16_T transferSize = MIN(fileNameSize, TARGET_IO_BUFFER_SIZE);
150 /* send file name string */
151 targetWriteDataWithCharToMemUnitWidening(fileName, &hostWordStdioBuffer[0], transferSize);
152 fileNameSize -= transferSize;
153 fileName += transferSize;
154 }
155 }
156 #else
157 /* send file name string */
158 targetWriteDataWithErrorCheck((const MemUnit_T *)fileName, fileNameSize);
159 #endif
160
161 /* return fid, THEN increment it */
162 return (unsigned short) (fid++); /* unsigned short is at least 16-bits
163 * wide. See header file for more
164 * information on why this cast is
165 * required. */
166 }
167
168 void targetFprintf(unsigned short targetFid, const char * fmt, ...) {
169 va_list argptr;
170 uint16_T fprintSize;
171 int vsFprintSize;
172 MemUnit_T responseId = XIL_RESPONSE_FPRINTF;
173 MemUnit_T errorId = TARGET_IO_SUCCESS;
174 const uint16_T targetFid16 = (uint16_T) targetFid; /* We only use the
175 * lowermost 16 bits of
176 * targetFid. unsigned
177 * int is guaranteed to
178 * be at least 16 bits
179 * wide. See header file
180 * for more information
181 * on why this cast is
182 * required. */
183
184 va_start(argptr, fmt);
185 #ifdef VSNPRINTF_AVAILABLE
186 /* size arg includes '\0', return value does not */
187 vsFprintSize = vsnprintf(&targetStdioBuffer[0], TARGET_IO_BUFFER_SIZE, fmt, argptr);
188 #else
189 vsFprintSize = vsprintf(&targetStdioBuffer[0], fmt, argptr);
190 #endif
191 if ((vsFprintSize < 0) || (vsFprintSize >= TARGET_IO_BUFFER_SIZE)) {
192 /* set error id if error or buffer overruns */
193 errorId = TARGET_IO_BUFFER_TRUNC;
194 /* do not send any data */
195 fprintSize = 0;
196 } else {
197 /* add one for the terminating null character */
198 fprintSize = (uint16_T) vsFprintSize + 1;
199 }
200 va_end(argptr);
201
202 /* send response id */
203 targetWriteDataWithErrorCheck(&responseId, sizeof(responseId));
204 /* send error id */
205 targetWriteDataWithErrorCheck(&errorId, sizeof(errorId));
206 /* send file id*/
207 targetWriteDataWithErrorCheck((MemUnit_T *)&targetFid16,
208 sizeof(targetFid16));
209 /* send fprintSize */
210 targetWriteDataWithErrorCheck((MemUnit_T *)&fprintSize, sizeof(fprintSize));
211 if (fprintSize > 0) {
212 #ifdef HOST_WORD_ADDRESSABLE_TESTING
213 /* send data */
214 targetWriteDataWithCharToMemUnitWidening(&targetStdioBuffer[0], &hostWordStdioBuffer[0], fprintSize);
215 #else
216 /* send data */
217 targetWriteDataWithErrorCheck((MemUnit_T *)&targetStdioBuffer[0], fprintSize);
218 #endif
219 }
220 return;
221 }
222
|